/**
 * ToolManager - 工具管理器
 * 基于 Augment Code 的工具执行机制
 */

import { EventEmitter } from 'events';
import { 
  ToolExecutor, 
  ToolType, 
  ToolExecutionResult, 
  ConversationContext 
} from './types';

export class ToolManager extends EventEmitter {
  private executors = new Map<ToolType, ToolExecutor>();
  private executionQueue: Array<{
    id: string;
    tool: ToolType;
    input: unknown;
    context: ConversationContext;
    resolve: (result: ToolExecutionResult) => void;
    reject: (error: Error) => void;
  }> = [];
  private isProcessing = false;
  private maxConcurrentExecutions = 3;
  private activeExecutions = new Set<string>();

  constructor(executors: ToolExecutor[] = []) {
    super();
    this.registerExecutors(executors);
  }

  /**
   * 注册工具执行器
   */
  registerExecutor(executor: ToolExecutor): void {
    const toolTypes = executor.getToolTypes();
    for (const toolType of toolTypes) {
      this.executors.set(toolType, executor);
    }
    this.emit('executorRegistered', { executor, toolTypes });
  }

  /**
   * 批量注册工具执行器
   */
  registerExecutors(executors: ToolExecutor[]): void {
    for (const executor of executors) {
      this.registerExecutor(executor);
    }
  }

  /**
   * 移除工具执行器
   */
  unregisterExecutor(toolType: ToolType): boolean {
    const removed = this.executors.delete(toolType);
    if (removed) {
      this.emit('executorUnregistered', toolType);
    }
    return removed;
  }

  /**
   * 执行工具
   */
  async executeToolAsync(
    tool: ToolType,
    input: unknown,
    context: ConversationContext
  ): Promise<ToolExecutionResult> {
    const executor = this.executors.get(tool);
    if (!executor) {
      throw new Error(`No executor registered for tool: ${tool}`);
    }

    if (!executor.canExecute(tool)) {
      throw new Error(`Executor cannot execute tool: ${tool}`);
    }

    const executionId = this.generateExecutionId();
    
    return new Promise<ToolExecutionResult>((resolve, reject) => {
      this.executionQueue.push({
        id: executionId,
        tool,
        input,
        context,
        resolve,
        reject
      });

      this.processQueue();
    });
  }

  /**
   * 同步执行工具（立即执行，不排队）
   */
  async executeToolSync(
    tool: ToolType,
    input: unknown,
    context: ConversationContext
  ): Promise<ToolExecutionResult> {
    const executor = this.executors.get(tool);
    if (!executor) {
      throw new Error(`No executor registered for tool: ${tool}`);
    }

    if (!executor.canExecute(tool)) {
      throw new Error(`Executor cannot execute tool: ${tool}`);
    }

    const executionId = this.generateExecutionId();
    
    try {
      this.emit('toolExecutionStarted', { executionId, tool, input });
      
      const result = await executor.execute(tool, input, context);
      
      this.emit('toolExecutionCompleted', { executionId, tool, result });
      
      return result;
    } catch (error) {
      this.emit('toolExecutionFailed', { executionId, tool, error });
      throw error;
    }
  }

  /**
   * 处理执行队列
   */
  private async processQueue(): Promise<void> {
    if (this.isProcessing || this.executionQueue.length === 0) {
      return;
    }

    this.isProcessing = true;

    while (
      this.executionQueue.length > 0 && 
      this.activeExecutions.size < this.maxConcurrentExecutions
    ) {
      const execution = this.executionQueue.shift();
      if (!execution) break;

      this.activeExecutions.add(execution.id);
      
      // 异步执行工具
      this.executeInBackground(execution);
    }

    this.isProcessing = false;
  }

  /**
   * 后台执行工具
   */
  private async executeInBackground(execution: {
    id: string;
    tool: ToolType;
    input: unknown;
    context: ConversationContext;
    resolve: (result: ToolExecutionResult) => void;
    reject: (error: Error) => void;
  }): Promise<void> {
    try {
      this.emit('toolExecutionStarted', {
        executionId: execution.id,
        tool: execution.tool,
        input: execution.input
      });

      const result = await this.executeToolSync(
        execution.tool,
        execution.input,
        execution.context
      );

      execution.resolve(result);
      
    } catch (error) {
      execution.reject(error instanceof Error ? error : new Error(String(error)));
    } finally {
      this.activeExecutions.delete(execution.id);
      
      // 继续处理队列
      if (this.executionQueue.length > 0) {
        this.processQueue();
      }
    }
  }

  /**
   * 检查工具是否可用
   */
  isToolAvailable(tool: ToolType): boolean {
    const executor = this.executors.get(tool);
    return executor ? executor.canExecute(tool) : false;
  }

  /**
   * 获取所有可用的工具类型
   */
  getAvailableTools(): ToolType[] {
    const tools: ToolType[] = [];
    for (const [toolType, executor] of this.executors) {
      if (executor.canExecute(toolType)) {
        tools.push(toolType);
      }
    }
    return tools;
  }

  /**
   * 获取工具执行器
   */
  getExecutor(tool: ToolType): ToolExecutor | undefined {
    return this.executors.get(tool);
  }

  /**
   * 取消所有待执行的工具
   */
  cancelPendingExecutions(): void {
    const cancelledCount = this.executionQueue.length;
    
    for (const execution of this.executionQueue) {
      execution.reject(new Error('Execution cancelled'));
    }
    
    this.executionQueue = [];
    
    this.emit('pendingExecutionsCancelled', { cancelledCount });
  }

  /**
   * 获取执行统计信息
   */
  getExecutionStats() {
    return {
      queueLength: this.executionQueue.length,
      activeExecutions: this.activeExecutions.size,
      maxConcurrentExecutions: this.maxConcurrentExecutions,
      registeredTools: this.executors.size,
      availableTools: this.getAvailableTools().length
    };
  }

  /**
   * 设置最大并发执行数
   */
  setMaxConcurrentExecutions(max: number): void {
    if (max < 1) {
      throw new Error('Max concurrent executions must be at least 1');
    }
    this.maxConcurrentExecutions = max;
    this.emit('maxConcurrentExecutionsChanged', max);
  }

  /**
   * 生成执行ID
   */
  private generateExecutionId(): string {
    return `exec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 清理资源
   */
  dispose(): void {
    this.cancelPendingExecutions();
    this.executors.clear();
    this.activeExecutions.clear();
    this.removeAllListeners();
  }
}

/**
 * 基础工具执行器抽象类
 */
export abstract class BaseToolExecutor implements ToolExecutor {
  protected supportedTools: ToolType[] = [];

  constructor(supportedTools: ToolType[]) {
    this.supportedTools = supportedTools;
  }

  abstract execute(
    tool: string, 
    input: unknown, 
    context: ConversationContext
  ): Promise<ToolExecutionResult>;

  canExecute(toolType: ToolType): boolean {
    return this.supportedTools.includes(toolType);
  }

  getToolTypes(): ToolType[] {
    return [...this.supportedTools];
  }

  /**
   * 创建成功结果
   */
  protected createSuccessResult(result: any, metadata?: Record<string, any>): ToolExecutionResult {
    return {
      success: true,
      result,
      metadata
    };
  }

  /**
   * 创建错误结果
   */
  protected createErrorResult(error: string, metadata?: Record<string, any>): ToolExecutionResult {
    return {
      success: false,
      error,
      metadata
    };
  }

  /**
   * 验证输入参数
   */
  protected validateInput(input: unknown, schema: any): boolean {
    // 这里可以实现更复杂的验证逻辑
    return input !== null && input !== undefined;
  }
}
